package com.haixiaoke.saas.house.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.haixiaoke.saas.apartment.domain.OrderVO;
import com.haixiaoke.saas.common.constant.HouseConstants;
import com.haixiaoke.saas.common.enums.OrderStateEnum;
import com.haixiaoke.saas.house.domain.*;
import com.haixiaoke.saas.house.service.IHouseDynamicService;
import com.haixiaoke.saas.order.domain.Order;
import com.haixiaoke.saas.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 房态管理 ServiceImpl
 *
 * @author qixi
 * @date 2023/10/24
 */
@Service
public class HouseDynamicServiceImpl implements IHouseDynamicService {

    @Autowired
    private EstateServiceImpl estateService;

    @Autowired
    private HouseServiceImpl houseService;

    @Autowired
    private SubHouseServiceImpl subordinateHouseService;

    @Autowired
    private IOrderService orderService;

    public HouseDynamic selectHouseStatusStatistics(House house) {
        HouseDynamic houseDynamic = new HouseDynamic();
        HouseStatus houseStatus = houseService.selectHouseStatus(house);
        houseDynamic.setHouseStatus(houseStatus);
        List<EstateTree> estateTreeList = estateService.selectEstateTreeList(house);
        estateTreeList = estateTreeList.stream().filter(m -> ObjectUtil.isNotNull(m.getChildren())).collect(Collectors.toList());
        houseDynamic.setEstateTreeList(estateTreeList);
        return houseDynamic;
    }

    @Override
    public Map selectHouseTreeList(House house) {

        List<House> houses = houseService.selectHouseListByInfo(house);
        houses.addAll(subordinateHouseService.selectSubHouseListConvertHouse(house));
        // 根据楼盘楼栋单元楼层构建树形结构
        Map<Estate, Map<Building, Map<Unit, Map<Integer, List<House>>>>> houseInfoMap = houses.stream().collect(Collectors.groupingBy(House::getEstate, Collectors.groupingBy(House::getBuilding, Collectors.groupingBy(House::getUnit, Collectors.groupingBy(House::getFloors)))));

        for (Estate estate : houseInfoMap.keySet()) {
            Map<Building, Map<Unit, Map<Integer, List<House>>>> buildingMap = houseInfoMap.get(estate);
            for (Building building : buildingMap.keySet()) {
                double vacancyRate;
                Integer vacancyHouseNumber = 0;
                Integer totalHouseNumber = 0;
                Map<Unit, Map<Integer, List<House>>> unitMap = buildingMap.get(building);
                for (Unit unit : unitMap.keySet()) {
                    Map<Integer, List<House>> floorMap = unitMap.get(unit);
                    for (Integer floor : floorMap.keySet()) {
                        List<House> houseList = floorMap.get(floor);
                        for (House house1 : houseList) {
                            if (StrUtil.equals(house1.getHouseState(), HouseConstants.HOUSE_STATE_VACANCY)) {
                                vacancyHouseNumber++;
                            }
                            totalHouseNumber++;
                        }
                    }
                }
                vacancyRate = NumberUtil.div(vacancyHouseNumber, totalHouseNumber).doubleValue();
                vacancyRate = NumberUtil.round(vacancyRate, 2, RoundingMode.DOWN).doubleValue();
                building.setVacancyRate(vacancyRate);
            }
        }
        return houseInfoMap;
    }

    @Override
    public List<House> selectHouseListByInfo(House house) {
        List<House> houses = houseService.selectHouseListByInfo(house);
        houses.addAll(subordinateHouseService.selectSubHouseListConvertHouse(house));
        return houses;
    }

    @Override
    public List<House> conditionList(House house) {
        List<House> houseList = houseService.conditionList(house);
        Order order = new Order();
        order.setCheckInTime(house.getStartTime());
        order.setCheckOutTime(house.getEndTime());
        order.setOrderType(house.getOrderType());
        Map<String, List<OrderVO>> voMap = null;
        if (CollectionUtil.isNotEmpty(houseList)) {
            order.setHouseIds(houseList.stream().map(House::getHouseId).collect(Collectors.toList()));
            List<OrderVO> voList = orderService.conditionList(order);
            if (CollectionUtil.isNotEmpty(voList)) {
                voMap = voList.stream().collect(Collectors.groupingBy(OrderVO::getHouseId));
            }
        }

        for (House h : houseList) {
            if (voMap != null) {
                List<OrderVO> orderVOList = voMap.get(h.getHouseId());
                if (CollectionUtil.isNotEmpty(orderVOList)) {
                    if (StrUtil.isNotBlank(orderVOList.get(0).getLinkedOrderId()) &&
                            StrUtil.equals(Order.ORDER_TYPE_SHORT_LEASE, orderVOList.get(0).getOrderType())) {
                        Order parentOrder = orderService.selectOrderById(orderVOList.get(0).getLinkedOrderId());
                        orderVOList.get(0).setOrderState(parentOrder.getOrderState());
                    }
                    List<Integer> indexList = new ArrayList<>();
                    for (int result = 0; result < orderVOList.size(); result++) {
                        if ((result + 1) == orderVOList.size()) {
                            continue;
                        }
                        OrderVO vo = orderVOList.get(result);
                        if (StrUtil.equals(Order.ORDER_TYPE_LONG_LEASE, orderVOList.get(0).getOrderType())) {
                            continue;
                        }
                        OrderVO reletVO = orderVOList.get(result + 1);
                        if (OrderStateEnum.ORDER_STATE_CHECKING_OUT.getValue().equals(vo.getOrderState()) ||
                                OrderStateEnum.ORDER_STATE_COMPLETED.getValue().equals(vo.getOrderState())) {
                            if (ObjectUtil.isNotEmpty(reletVO)) {
                                boolean flag = StrUtil.equals(reletVO.getLinkedOrderId(), vo.getOrderId()) ||
                                        StrUtil.equals(reletVO.getLinkedOrderId(), vo.getLinkedOrderId());
                                if (flag) {
                                    indexList.add(result + 1);
                                }
                            }
                        }
                    }
                    if (!indexList.isEmpty()) {
                        indexList.sort((a, b) -> Integer.compare(b, a));
                        for (int index : indexList) {
                            orderVOList.remove(index);
                        }
                    }
                    h.setOrderVOList(orderVOList);
                }
            }
        }
        return houseList;
    }

    @Override
    public List<House> conditionCard(House house) {
        return orderService.conditionCard(house);
    }
}
